package http

import (
	"fmt"
	"gitee.com/Cauchy_AQ/gokv/utils"
	"github.com/gin-gonic/gin"
)

func gokvGetHandler(c *gin.Context) {
	key := c.Query("key")

	value, err := db.Get([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	ResponseSuccess(c, CodeSuccess, gin.H{
		"value": string(value),
	})
	return
}

func gokvPutHandler(c *gin.Context) {
	p := new(paramKeyValue)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	if err := db.Put([]byte(p.Key), []byte(p.Value)); err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	ResponseSuccess(c, CodeSuccess, nil)
	return
}

func gokvDeleteHandler(c *gin.Context) {
	key := c.Query("key")

	err := db.Delete([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	ResponseSuccess(c, CodeSuccess, nil)
	return
}

func gokvListKeysHandler(c *gin.Context) {
	keys := db.ListKeys()

	result := utils.ByteArrayToStringArray(keys)
	ResponseSuccess(c, CodeSuccess, gin.H{
		"keys": result,
	})
	return
}

func gokvStatHandler(c *gin.Context) {
	stat := db.Stat()
	ResponseSuccess(c, CodeSuccess, gin.H{
		"status": stat,
	})
	return
}

func gokvMergeHandler(c *gin.Context) {
	if err := db.Merge(); err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, nil)
	return
}

func gokvBackUpHandler(c *gin.Context) {
	path := c.Query("path")
	if err := db.BackUp(path); err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, nil)
	return
}

// ================================ redis =============================== //

// ===================== string ================== //
func redisGetHandler(c *gin.Context) {
	key := c.Query("key")
	value, err := redis.Get([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"value": string(value),
	})
	return
}

func redisSetHandler(c *gin.Context) {
	p := new(paramKeyValueRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	if err := redis.Set([]byte(p.Key), []byte(p.Value), p.TTL); err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, nil)
	return
}

// ===================== hash ================== //

func redisHSetHandler(c *gin.Context) {
	p := new(paramKeyFieldValueRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	ok, err := redis.HSet([]byte(p.Key), []byte(p.Field), []byte(p.Value))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"status": ok,
	})
	return
}

func redisHGetHandler(c *gin.Context) {
	p := new(paramKeyFieldValueRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	value, err := redis.HGet([]byte(p.Key), []byte(p.Field))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"value": string(value),
	})
	return
}

func redisHDelHandler(c *gin.Context) {
	p := new(paramKeyFieldValueRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	ok, err := redis.HDel([]byte(p.Key), []byte(p.Field))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	ResponseSuccess(c, CodeSuccess, gin.H{
		"status": ok,
	})
	return
}

func redisHExistsHandler(c *gin.Context) {
	p := new(paramKeyFieldValueRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	ok, err := redis.HExists([]byte(p.Key), []byte(p.Field))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	ResponseSuccess(c, CodeSuccess, gin.H{
		"status": ok,
	})
	return
}

func redisHKeysHandler(c *gin.Context) {
	p := new(paramKeyFieldValueRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	keys, err := redis.HKeys([]byte(p.Key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	ResponseSuccess(c, CodeSuccess, gin.H{
		"keys": fmt.Sprintf("%s", keys),
	})
	return
}

func redisHValsHandler(c *gin.Context) {
	p := new(paramKeyFieldValueRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	vals, err := redis.HVals([]byte(p.Key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	ResponseSuccess(c, CodeSuccess, gin.H{
		"vals": fmt.Sprintf("%s", vals),
	})
	return
}

func redisHLenHandler(c *gin.Context) {
	key := c.Query("key")
	size := redis.HLen([]byte(key))
	ResponseSuccess(c, CodeSuccess, gin.H{
		"len": size,
	})
	return
}

// ===================== set ================== //
func redisSAddHandler(c *gin.Context) {
	p := new(paramKeyMembersRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	members := make([][]byte, len(p.Members))
	for i, m := range p.Members {
		members[i] = []byte(m)
	}

	n, err := redis.SAdd([]byte(p.Key), members...)
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"size": n,
	})
	return
}

func redisSRemHandler(c *gin.Context) {
	p := new(paramKeyMembersRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	members := utils.StringArrayToByteArray(p.Members)

	n, err := redis.SRem([]byte(p.Key), members...)
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"size": n,
	})
	return
}

func redisSMembersHandler(c *gin.Context) {
	key := c.Query("key")
	members, err := redis.SMembers([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	elements := utils.ByteArrayToStringArray(members)

	ResponseSuccess(c, CodeSuccess, gin.H{
		"members": elements,
	})
	return
}

func redisSIsMemberHandler(c *gin.Context) {
	p := new(paramKeyMemberRedis)

	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	ok := redis.SIsMember([]byte(p.Key), []byte(p.Member))
	ResponseSuccess(c, CodeSuccess, gin.H{
		"status": ok,
	})
	return
}

func redisSCardHandler(c *gin.Context) {
	key := c.Query("key")
	n, err := redis.SCard([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"size": n,
	})
	return
}

// ===================== list ================== //

func redisLPushHandler(c *gin.Context) {
	p := new(paramKeyElementRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	n, err := redis.LPush([]byte(p.Key), []byte(p.Element))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"size": n,
	})
	return
}

func redisLPopHandler(c *gin.Context) {
	key := c.Query("key")
	element, err := redis.LPop([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"element": string(element),
	})
	return
}
func redisRPushHandler(c *gin.Context) {
	p := new(paramKeyElementRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	n, err := redis.RPush([]byte(p.Key), []byte(p.Element))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"size": n,
	})
	return
}
func redisRPopHandler(c *gin.Context) {
	key := c.Query("key")
	element, err := redis.RPop([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"element": string(element),
	})
	return
}
func redisLLenHandler(c *gin.Context) {
	key := c.Query("key")
	n, err := redis.LLen([]byte(key))
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"size": n,
	})
	return
}
func redisLIndexHandler(c *gin.Context) {
	p := new(paramKeyIndexRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	element, err := redis.LIndex([]byte(p.Key), p.Index)
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}
	ResponseSuccess(c, CodeSuccess, gin.H{
		"element": string(element),
	})
	return
}
func redisLRangeHandler(c *gin.Context) {
	p := new(paramKeyStartStopRedis)
	if err := c.ShouldBindJSON(p); err != nil {
		ResponseError(c, CodeInvalidParam)
		return
	}

	elems, err := redis.LRange([]byte(p.Key), p.Start, p.Stop)
	if err != nil {
		ResponseErrorWithMsg(c, CodeServerBusy, err.Error())
		return
	}

	elements := utils.ByteArrayToStringArray(elems)

	ResponseSuccess(c, CodeSuccess, gin.H{
		"elements": elements,
	})
	return
}
